/****************************************************************************
 * Copyright 2009 Huascar A. Sanchez                                        *
 *                                                                          *
 * Licensed under the Apache License, Version 2.0 (the "License");          *
 * you may not use this file except in compliance with the License.         *
 * You may obtain a copy of the License at                                  *
 *                                                                          *
 *     http://www.apache.org/licenses/LICENSE-2.0                           *
 *                                                                          *
 * Unless required by applicable law or agreed to in writing, software      *
 * distributed under the License is distributed on an "AS IS" BASIS,        *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
 * See the License for the specific language governing permissions and      *
 * limitations under the License.                                           *
 ****************************************************************************/
package com.gotobject.filter.common;

import static com.gotobject.filter.FilterQ.from;
import static com.gotobject.filter.common.Aggregations.count;
import static com.gotobject.filter.common.Predicates.eq;
import static com.gotobject.filter.common.Predicates.gt;
import static com.gotobject.filter.common.Predicates.lt;
import static com.gotobject.filter.common.Predicates.mod;
import static com.gotobject.filter.common.Iterables.concat;
import static com.gotobject.filter.common.Iterables.distinct;
import static com.gotobject.filter.common.Iterables.except;
import static com.gotobject.filter.common.Iterables.intersect;
import static com.gotobject.filter.common.Iterables.union;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.junit.Assert;
import org.junit.Test;

/**
 * @author huascar.sanchez@gmail.com (Huascar A. Sanchez)
 */
public class IterablesTest {
	@Test
	public void testUnion() throws Exception {
		final List<Integer> a = Arrays.asList(1, 2, 3, 4, 5);
		final List<Integer> b = Arrays.asList(4, 8, 6, 9, 10);

		final Iterable<Integer> result = union(a, b);
		Assert.assertSame("ended up with 9 elements", 9, count(result));
	}


	@SuppressWarnings({"unchecked"})
	@Test
	public void testUnion_Raw() throws Exception {
		final List a = Arrays.asList(1, 2, 3, 4, 5);
		final List b = Arrays.asList("1", "2", "3");

		final Iterable result = union(a, b);
		Assert.assertSame("ended up with 9 elements", 8, count(result));
	}


	@Test
	public void testIntersect() throws Exception {
		final List<Integer> a = Arrays.asList(1, 2, 3, 4, 5);
		final List<Integer> b = Arrays.asList(4, 8, 6, 9, 10);

		final Iterable<Integer> result = intersect(a, b);
		Assert.assertSame("ended up with 1 element", 1, count(result));
	}


	@SuppressWarnings({"unchecked"})
	@Test
	public void testIntersect_Raw() throws Exception {
		final List a = Arrays.asList(1, 2, 3, 4, 5);
		final List b = Arrays.asList("1", "2", "3", 5);

		final Iterable result = intersect(a, b);
		Assert.assertSame("ended up with 1 element", 1, count(result));
	}

	@Test
	public void testExcept() throws Exception {
		final List<Integer> a = Arrays.asList(1, 2, 3, 4, 5);
		final List<Integer> b = Arrays.asList(2, 3, 4);

		final Iterable<Integer> result = except(a, b);
		Assert.assertSame("ended up with 2 elements", 2, count(result));
	}


	@SuppressWarnings({"unchecked"})
	@Test
	public void testExcept_Raw() throws Exception {
		final List a = Arrays.asList("1", "2", "3", 4, 5);
		final List b = Arrays.asList("1", "2", "3");

		final Iterable result = except(a, b);
		Assert.assertSame("ended up with 2 element", 2, count(result));
	}


	@Test
	public void testConcat() throws Exception {
		final List<Integer> a = Arrays.asList(1, 2, 3, 3, 4);
		final List<Integer> b = Arrays.asList(2, 3, 4);

		final Iterable<Integer> result = concat(a, b);
		Assert.assertSame("ended up with 8 element", 8, count(result));

		Assert.assertSame("ended up with 3 3s", 3, count(result, eq(3)));
		Assert.assertSame("ended up with 2 4s", 2, count(result, eq(4)));
		
	}


	@Test
	public void testDistinct() throws Exception {
		final List<Integer> 	a 		= Arrays.asList(1, 2, 3, 3, 3, 4, 4);
		final Iterable<Integer> result 	= distinct(a);

		Assert.assertSame("ended up with 4 elements", 4, count(result));
	}


	@Test
	public void testMultipleIterablesInASingleLoop() throws Exception {
		final List<Integer> result = new CopyOnWriteArrayList<Integer>();
		for(Integer each : concat(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6))){
			result.add(each);
		}

		Assert.assertSame("ended up with 6 elements", 6, count(result));
		
	}


	@Test
	public void testComplexityScenario() throws Exception {
		final List<Integer> a = Arrays.asList(1, 2, 3, 4, 5);
		final List<Integer> b = Arrays.asList(4, 8, 6, 9, 10);

		final Iterable<Integer> result = intersect(
			from(a).where(mod(2).and(lt(5)).and(gt(2))).select(),
			from(b).select(3)
		);

		Assert.assertSame("ended up with 1 element", 1, count(result));

	}

}
